﻿using System;
using NHibernate;
using CRC.GestionSalones.Dominio.Clases;
using System.Collections.Generic;
using CRC.Inspecciones.Dominio.Clases;
using System.Collections;
using CRC.GestionSalones.Presentacion;
using CRC.Incidencias.Dominio.Clases;

namespace CRC.GestionSalones.Controladores
{
    public class ControladorModificarSalon : ControladorBaseSalon, IControladorCongregacion

    {
        private static String strQryExisteProyecto = "from Salon s where s.Proyecto='{0}'";
        private static String strQryExisteCongregacion = "from Congregacion c where c.NombreCRC=:NombreCRC";

        private Salon salon = null;
        private Congregacion cong = null;
        private Persona supPresidente = null;
        private Persona secretario = null;
        private Persona supCircuito = null;

        public Object[] obtenerInformacionSalon(int pIntSalon) {
            ISession session = null;
            ITransaction tx = null;
            Object[] res = new Object[14];
            try 
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                tx = session.BeginTransaction();

                this.salon = (Salon)session.Get(typeof(Salon), pIntSalon);
                res[0] = salon.Proyecto;
                res[1] = salon.Nombre_Salon;
                res[2] = salon.Telefono;
                if (salon.Municipio != null)
                {
                    res[3] = salon.Municipio.Provincia.Id;
                    res[4] = salon.Municipio.Id;
                }

                res[5] = salon.Zona.Id;
                res[6] = salon.Direccion;
                res[7] = salon.CP;
                res[8] = salon.TipoPropiedad.Id;
                res[9] = salon.GPS_Altitud;
                res[10] = salon.GPS_Latitud;

                LinkedList<Object[]> congregaciones = new LinkedList<Object[]>();
                res[11] = congregaciones;

                foreach (Congregacion asistente in salon.Asistentes)
                { 
                    Object[] congregacion = new Object[3];
                    congregacion[0] = asistente.Numero;
                    congregacion[1] = asistente.NombreCRC;
                    congregacion[2] = asistente.EsAnfitriona;
                    congregaciones.AddLast(congregacion);
                }

                LinkedList<Object[]> trazabilidadInspecciones = new LinkedList<Object[]>();
                res[12] = trazabilidadInspecciones;

                foreach (LineaSeguimientoInspeccion linea in salon.TrazabilidadInspecciones)
                { 
                    Object[] lineaInspeccion = new Object[4];
                    lineaInspeccion[0] = linea.Id;
                    lineaInspeccion[1] = linea.Estado.Descripcion;
                    lineaInspeccion[2] = linea.Fecha.ToShortDateString();
                    if (linea.Documento != null) lineaInspeccion[3] = linea.Documento.Id;
                    trazabilidadInspecciones.AddLast(lineaInspeccion);
                }

                LinkedList<Object[]> registroIncidencias = new LinkedList<Object[]>();
                res[13] = registroIncidencias;

                foreach (Incidencia inc in this.salon.IncidenciasNotificadas) 
                {
                    Object[] incidencia = new Object[6];

                    incidencia[0] = inc.Id;
                    incidencia[1] = inc.AfectaA.Codigo;
                    incidencia[2] = inc.AfectaA.EscribirRuta();
                    if (inc.AsignadoA == null)
                    {
                        incidencia[3] = string.Empty;
                    }
                    else {
                        incidencia[3] = inc.AsignadoA.Descripcion;
                    }
                    if (inc.FechaLimiteParaSolucion.HasValue)
                        incidencia[4] = inc.FechaLimiteParaSolucion.Value.ToShortDateString();
                    incidencia[5] = inc.Cerrada;
                    registroIncidencias.AddLast(incidencia);
                }
                return res;
            } 
            catch(HibernateException he) 
            {
                if (tx != null) {
                    tx.Rollback();
                    session.Close();
                }
                throw he;
            }
        }
        
        public Object[] obtenerDatosCongregacion(String pStrNombreCRC)
        {
            String strNombPresid = String.Empty, strNombSecre = String.Empty, strNombSupCircuito = String.Empty;

            foreach (Congregacion c in this.salon.Asistentes)
            {
                if (c.NombreCRC.CompareTo(pStrNombreCRC) == 0)
                {

                    this.cong = c;
                    this.supCircuito = c.SuperintendenteCircuito;
                    this.supPresidente = c.Presidente;
                    this.secretario = c.Secretario;

                    if (this.cong.Presidente != null) strNombPresid = this.cong.Presidente.NombreCompleto;
                    if (this.cong.Secretario != null) strNombSecre = this.cong.Secretario.NombreCompleto;
                    if (this.cong.SuperintendenteCircuito != null) strNombSupCircuito = this.cong.SuperintendenteCircuito.NombreCompleto;

                    return new Object[] { 
                            this.cong.Numero, 
                            this.cong.NombreCRC, 
                            this.cong.NombreSucursal,
                            this.cong.EsAnfitriona,
                            strNombPresid , 
                            strNombSecre, 
                            strNombSupCircuito, 
                            this.cong.Observaciones
                        };
                }
            }
            return null;
        }

        public void eliminarCongregacion(String pStrNombreCRC) 
        {
            ISession session = NHibernate.NHibernateHelper.GetCurrentSession();

            foreach (Congregacion c in this.salon.Asistentes)
            {
                if (c.NombreCRC.CompareTo(pStrNombreCRC) == 0)
                {
                    this.salon.Asistentes.Remove(c);
                    c.Salon = null;
                    session.Delete(c);
                    session.Flush();
                    return;
                }
            }
        }

        public void modificarCongregacion(
                    int pIntNum,
                    String pStrNombreCRC,
                    String pStrNombreSucursal,
                    Boolean pbEsAnfitriona,
                    String pStrObservaciones)
            {
                ISession session = null;
                ITransaction tx = null;

                try
                {
                    session = NHibernate.NHibernateHelper.GetCurrentSession();
                    tx = session.BeginTransaction();

                    //post: Si hemos añadido congregacion con numero pIntNum -> excepcion
                    foreach (Congregacion ass in this.salon.Asistentes)
                    {
                        if ((ass != this.cong) && (ass.NombreCRC.CompareTo(pStrNombreCRC) == 0))
                            throw new ApplicationException("¡Ya existe una congregación con este nombre!");
                    }

                    if (this.cong.NombreCRC.CompareTo(pStrNombreCRC) != 0) 
                    {
                        IQuery qry = session.CreateQuery(strQryExisteCongregacion).SetParameter("NombreCRC", pStrNombreCRC);
                        int nCongAux = qry.List().Count;

                        if (nCongAux > 0)
                            throw new ApplicationException("¡Ya existe una congregación con este nombre!");
                    }

                    this.cong.Numero = pIntNum;
                    this.cong.NombreCRC = pStrNombreCRC;
                    this.cong.NombreSucursal = pStrNombreSucursal;
                    this.cong.EsAnfitriona = pbEsAnfitriona;
                    this.cong.Presidente = this.supPresidente;
                    this.cong.Secretario = this.secretario;
                    this.cong.SuperintendenteCircuito = this.supCircuito;
                    this.cong.Observaciones = pStrObservaciones;

                    tx.Commit();

                    this.supPresidente = null;
                    this.secretario = null;
                    this.supCircuito = null;
                }
                catch (HibernateException he)
                {

                    if (tx != null) tx.Rollback();
                    session.Close();
                    throw he;
                }
            }

        public void añadirCongregacion(
            int pIntNum,
            String pStrNombreCRC, String 
            pStrNombreSucursal, 
            bool pbEsAnfitriona,
            String pStrObservaciones)
        {
            ISession session = null;
            ITransaction tx = null;

            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                tx = session.BeginTransaction();

                //post: Si hemos añadido congregacion con numero pIntNum -> excepcion
                foreach (Congregacion ass in this.salon.Asistentes)
                {
                    if (ass.NombreCRC.CompareTo(pStrNombreCRC) == 0)
                        throw new ApplicationException("¡Ya existe una congregación con este nombre!");
                }
                IQuery qry = session.CreateQuery(strQryExisteCongregacion).SetParameter("NombreCRC", pStrNombreCRC);
                IList<Congregacion> congAux = qry.List<Congregacion>();
                if (congAux.Count > 0)
                    throw new ApplicationException("¡Ya existe una congregación con este nombre! " + pIntNum);

                if (pbEsAnfitriona)
                {
                    foreach (Congregacion ass in this.salon.Asistentes)
                        ass.EsAnfitriona = false;
                }

                this.cong = new Congregacion(
                    pIntNum,
                    pStrNombreCRC,
                    pStrNombreSucursal,
                    pbEsAnfitriona,
                    this.salon,
                    pStrObservaciones,
                    this.supPresidente,
                    this.secretario,
                    this.supCircuito
                );

                //Creamos associacion bidireccional Salon <-> Congregacion
                this.salon.Asistentes.Add(this.cong);
                this.cong.Salon = this.salon;
                tx.Commit();

                this.supPresidente = null;
                this.secretario = null;
                this.supCircuito = null;
            }
            catch (HibernateException he)
            {

                if (tx != null) tx.Rollback();
                session.Close();
                throw he;
            }
        }

        public void nuevoPresidente(string pStrNombre, string pStrApellido1, string pStrApellido2, string pStrMovil, string pStrFijo, string pStrEmail)
        {
            ISession session = null;
            ITransaction tx = null;

            try
            {

                session = NHibernate.NHibernateHelper.GetCurrentSession();
                tx = session.BeginTransaction();

                TipoPersona tipoPresidente = (TipoPersona)session.Get(typeof(TipoPersona), 1);
                this.supPresidente = new Persona(pStrNombre, pStrApellido1, pStrApellido2,
                pStrFijo, pStrMovil, null, pStrEmail, tipoPresidente);

                tx.Commit();

            }
            catch (HibernateException he)
            {
                if (tx != null)
                {
                    tx.Rollback();
                    session.Close();
                }
                throw he;
            }
        }

        public object[] obtenerDatosPresidente()
        {
            if (this.supPresidente != null)
            {
                return new Object[] { 
                            this.supPresidente.Nombre, 
                            this.supPresidente.Apellido1, 
                            this.supPresidente.Apellido2, 
                            this.supPresidente.TelefonoFijo, 
                            this.supPresidente.TelefonoMovil1, 
                            this.supPresidente.Email 
                        };
            }
            return null;
        }

        public void modificarDatosPresidente(string pStrNombre, string pStrApellido1, string pStrApellido2, string pStrMovil, string pStrFijo, string pStrEmail)
        {
            this.supPresidente.Nombre = pStrNombre;
            this.supPresidente.Apellido1 = pStrApellido1;
            this.supPresidente.Apellido2 = pStrApellido2;
            this.supPresidente.TelefonoMovil1 = pStrMovil;
            this.supPresidente.TelefonoFijo = pStrFijo;
        }

        public void asignarPresidente(int pIntPresidente)
        {
            ISession session = null;

            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                this.supPresidente = (Persona)session.Get(typeof(Persona), pIntPresidente);
            }
            catch (HibernateException he)
            {
                session.Close();
                throw he;
            }
        }

        public void nuevoSecretario(string pStrNombre, string pStrApellido1, string pStrApellido2, string pStrMovil, string pStrFijo, string pStrEmail)
        {
            ISession session = null;
            ITransaction tx = null;

            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                tx = session.BeginTransaction();

                TipoPersona tipoSecretario = (TipoPersona)session.Get(typeof(TipoPersona), 2);
                this.secretario = new Persona(pStrNombre, pStrApellido1, pStrApellido2,
                    pStrFijo, pStrMovil, null, pStrEmail, tipoSecretario);

                tx.Commit();
            }
            catch (HibernateException he)
            {
                if (tx != null) tx.Rollback();
                session.Close();
                throw he;
            }
        }

        public object[] obtenerDatosSecretario()
        {
            if (this.secretario != null)
            {
                return new Object[] { 
                                this.secretario.Nombre, 
                                this.secretario.Apellido1, 
                                this.secretario.Apellido2, 
                                this.secretario.TelefonoFijo, 
                                this.secretario.TelefonoMovil1, 
                                this.secretario.Email 
                            };
            }
            return null;
        }

        public void modificarDatosSecretario(string pStrNombre, string pStrApellido1, string pStrApellido2, string pStrMovil, string pStrFijo, string pStrEmail)
        {               
            this.secretario.Nombre = pStrNombre;
            this.secretario.Apellido1 = pStrApellido1;
            this.secretario.Apellido2 = pStrApellido2;
            this.secretario.TelefonoMovil1 = pStrMovil;
            this.secretario.TelefonoFijo = pStrFijo;
            this.secretario.Email = pStrEmail;
        }

        public void asignarSecretario(int pIntSecretario)
        {
            ISession session = null;

            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                this.secretario = (Persona)session.Get(typeof(Persona), pIntSecretario);
            }
            catch (HibernateException he)
            {
                session.Close();
                throw he;
            }
        }

        public void asignarSuperintendenteCircuito(int pInSupCircuito)
        {
            ISession session = null;

            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                this.supCircuito = (Persona)session.Get(typeof(Persona), pInSupCircuito);
            }
            catch (HibernateException he)
            {
                session.Close();
                throw he;
            }
        }

        public Object[] obtenerDatosSuperintendenteCircuito()
        {
            if (this.supCircuito != null)
            {
                return new Object[] { 
                                this.supCircuito.Nombre, 
                                this.supCircuito.Apellido1, 
                                this.supCircuito.Apellido2, 
                                this.supCircuito.TelefonoFijo, 
                                this.supCircuito.TelefonoMovil1, 
                                this.supCircuito.Email 
                            };
            }
            return null;
        }

        public void modificarDatosSupCircuito(
                        String pStrNombre,
                        String pStrApellido1,
                        String pStrApellido2,
                        String pStrMovil,
                        String pStrFijo,
                        String pStrEmail)
        {
            this.supCircuito.Nombre = pStrNombre;
            this.supCircuito.Apellido1 = pStrApellido1;
            this.supCircuito.Apellido2 = pStrApellido2;
            this.supCircuito.TelefonoMovil1 = pStrMovil;
            this.supCircuito.TelefonoFijo = pStrFijo;
            this.supCircuito.Email = pStrEmail;
        }

        public void modificarSalon(
            String pStrNumProyecto,
            String pStrNombreSalon,
            int? pIntProvincia,
            int? pIntMunicipio,
            int pIntZona,
            String pStrDireccion,
            String pStrCPostal,
            String pStrAltitud,
            String pStrLatitud,
            int? pIntTelefono,
            String pStrObservaciones,
            String pStrTipoPropiedad
        )
        {
            ISession session = null;
            ITransaction tx = null;
            try
            {
                session = NHibernate.NHibernateHelper.GetCurrentSession();
                tx = session.BeginTransaction();

                if (pStrNumProyecto.CompareTo(this.salon.Proyecto) != 0) 
                { 
                    IList res = session.CreateQuery(String.Format(strQryExisteProyecto, pStrNumProyecto)).List();
                    if (res.Count > 0)
                        throw new ApplicationException("El número de proyecto ya está asignado");
                }

                Municipio munic = null;
                if (pIntMunicipio != null) munic = (Municipio)session.Get(typeof(Municipio), pIntMunicipio);
                TipoPropiedad tipoPropiedad = (TipoPropiedad)session.Get(typeof(TipoPropiedad), pStrTipoPropiedad);
                Zona zona = (Zona)session.Get(typeof(Zona), pIntZona);

                this.salon.Proyecto = pStrNumProyecto;
                this.salon.Nombre_Salon = pStrNombreSalon;
                this.salon.Municipio = munic;
                this.salon.Direccion = pStrDireccion;
                this.salon.CP = pStrCPostal;
                this.salon.GPS_Altitud = pStrAltitud;
                this.salon.GPS_Latitud = pStrLatitud;
                this.salon.Telefono = pIntTelefono;
                this.salon.Observaciones = pStrObservaciones;
                this.salon.TipoPropiedad = tipoPropiedad;

                zona.quitarSalon(this.salon); //quitar zona antigua
                zona.añadirSalon(this.salon); //asignar zona nueva

                session.Update(this.salon);

                tx.Commit();

            }
            catch (HibernateException he)
            {
                if (tx != null) tx.Rollback();
                session.Close();
                throw he;
            }

        }


        public void limpiarEstado()
        {
            this.supCircuito = null;
            this.supPresidente = null;
            this.secretario = null;
        }
    }
}
